import clr 
clr.AddReference('System.Windows.Forms')
clr.AddReference('System.Drawing')
from System.Windows.Forms import *
from System.Drawing import *
from math import *
from Function import *
from pointLibrary import *

class C:
    def __init__(self,r, g, b, a = 1):
        self.r = r
        self.g = g
        self.b = b
        self.a = a
    def __mul__(self, t):
        return C(self.r * t, self.g * t, self.b * t, self.a)
    def __rmul__(self, t):
        return C(self.r * t, self.g * t, self.b * t, self.a)
    def toColor(self):
        return Color.FromArgb(toEight(self.a), toEight(self.r), toEight(self.g), toEight(self.b))
    def __add__(self,c):
        return C(self.r + c.r,self.g + c.g,self.b + c.b, self.a + c.a)
    def __mul__(self,d):
        return C(self.r * d,self.g * d ,self.b *d,self.a * d)
    def __rmul__(self,d):
        return C(self.r * d,self.g * d ,self.b *d,self.a * d)
    def __div__(self,d):
        return self*(1.0/d)
    def lerp(self, p, t):
        r = (1-t)*self.r + t*p.r
        g = (1-t)*self.g + t*p.g
        b = (1-t)*self.b + t*p.b
        a = (1-t)*self.a + t*p.a
        return C(r, g, b, a)

    def composite(self, x):
        alphaa = self.a
        alphab = x.a
        alphai = alphaa + (alphab * (1 - alphaa))
        if alphai == 0:
            return clear
        r = (1/alphai) * ((self.r * alphaa) + (x.r * alphab * (1 - alphaa)))
        g = (1/alphai) * ((self.g * alphaa) + (x.g * alphab * (1 - alphaa)))
        b = (1/alphai) * ((self.b * alphaa) + (x.b * alphab * (1 - alphaa)))
        return C(r, g, b, alphai)

    def h(self):
        return 

    def s(self):
        return

    def v(self):
        return

def grey(x):
    return C(x,x,x)

def rgb(r, g, b):
    r = r / 255.0
    g = g / 255.0
    b = b / 255.0
    return C(r, g, b)

def hsv(h,s,v):
    h = float(h)
    s = float(s)
    v = float(v)
    r,g,b = hsvtorgb(h,s,v)
    return C(r,g,b)

def hsvtorgb(h, s, v):
    Pi = 3.141592653 
    h = float(h)
    s = float(s)
    v = float(v)
    r, g, b = 0,0,0
    h60 = h / (Pi / 3)
    h60f = floor(h60)
    hi = int(h60f) % 6
    f = h60 - h60f
    p = v * (1 - s)
    q = v * (1 - f * s)
    t = v * (1 - (1 - f) * s)
    r, g, b = 0, 0, 0
    if hi == 0: r, g, b = v, t, p
    elif hi == 1: r, g, b = q, v, p
    elif hi == 2: r, g, b = p, v, t
    elif hi == 3: r, g, b = p, q, v
    elif hi == 4: r, g, b = t, p, v
    elif hi == 5: r, g, b = v, p, q
    return r, g, b

def rgbtohsv(c):
    Pi = 3.141592653 
    r = c.r
    g = c.g
    b = c.b
    mx = max(r, g, b)
    mn = min(r, g, b)
    df = mx-mn
    if mx == mn:
        h = 0
    elif mx == r:
        h = ((Pi / 3) * ((g - b)/ df) + 1) % 1
    elif mx == g:
        h = ((Pi / 3) * ((b - r)/ df) + ((2 * Pi) / 3)) % 1
    elif mx == b:
        h = ((Pi / 3) * ((r - g)/ df) + ((4 * Pi) / 3)) % 1
    if mx == 0:
        s = 0
    else:
        s = df/mx
    v = mx
    return h,s,v

def toEight(x):
        x = int(x * 256)
        if x < 0:
            return 0
        if x > 255:
            return 255
        return x
to8 = toEight

#Color Functions
white = C(1,1,1,1)
black = C(0,0,0,1)
clear = C(0,0,0,0)
yellow = C(0,1,1,1)
red = C(1,0,0,1)
green = C(0,1,0,1)
blue = C(0,0,1,1)

composite = lambda ca, cb: ca.composite(cb)
grey = C(0.5,0.5,0.5,0.5)
togrey = lambda c: C(c,c,c)
fadeC =  lambda t: lambda c2: c2.lerp(clear,t) 
lightenC = lambda t: lambda c2: c2.lerp(white,t)
darkenC = lambda t: lambda c2: c2.lerp(black,t)
shadeC = lambda t: lambda c2: c2.lerp(grey,t)
distanceC = lambda c: lambda c2: sqrt((c.r - c2.r)**2 + (c.g - c2.g)**2 + (c.b - c2.g)**2 + (c.a - c2.a)**2) # photo to mask, 
distanceC2 = lambda c: sqrt((c.r - 1)**2 + (c.g - 1)**2 + (c.b - 1)**2)
withinC = lambda d: lambda c: lambda c1: distanceC2(c)(c1) < d*d #image, pick a color, show the image, if else statement
negC = lambda c: C(1 - c.r, 1 - c.g, 1 - c.b, c.a) 

def maskfromcolor(c, d):
       return lambda p: withinC (d)(c)

def mask(m, f1, f2):
       return lambda p: f1(p) if m(p) else f2(p)

def blend(m, f1, f2):
       return lambda p: lerp(m(p), f1(p), f2(p))

def over(image1, image2):
        return lambda p: composite(image1(p), image2(p))

def fade(image, t):
    return lambda p: fadeC(t) (image(p))

def addh(dh):
    def f(c):
        (h,s,v) = rgbtohsv(c)
        return hsv(h+dh, s, v)
    return f

def adds(ds):
    def f(c):
        (h,s,v) = rgbtohsv(c)
        return hsv(h, s+ds, v)
    return f

def addv(dv):
    def f(c):
        (h,s,v) = rgbtohsv(c)
        return hsv(h, s, v+dv)
    return f
    